#include "Subsystems/BlockBehaviors/SubsystemThrowableBlockBehavior.h"
#include "Subsystems/SubsystemProjectiles.h"
#include "Managers/BlocksManager.h"
#include "Components/ComponentMiner.h"
#include "Components/ComponentCreature.h"
#include "Components/ComponentCreatureModel.h"
#include "Components/ComponentBody.h"
#include "Components/ComponentPlayer.h"
#include "Components/ComponentLevel.h"
#include "GameRandom.hpp"

namespace PocketSurvival
{
    bool SubsystemThrowableBlockBehavior::onAim(const Ray3 &aim, ComponentMiner *componentMiner, AimState state)
    {
        if (AimState::Completed == state)
        {
            // const Vector3 &bodyPosition = componentMiner->componentCreature->componentBody->position;
            Vector3 eyePosition = componentMiner->componentCreature->componentCreatureModel->getEyePosition();
            Vector3 vector = eyePosition + componentMiner->componentCreature->componentBody->getMatrix().getRight() * 0.4f;

            auto v = Vector3::Normalize(vector + aim.Direction * 10.0f - vector);

            int32_t activeSlotIndex = componentMiner->inventory->getActiveSlotIndex();
            int32_t slotValue = componentMiner->inventory->getSlotValue(activeSlotIndex);
            int32_t slotCount = componentMiner->inventory->getSlotCount(activeSlotIndex);
            int32_t num = Terrain::ExtractContents(slotValue);
            Block *block = GameSingleton::blocksManager->blocks[num];
            if (slotCount > 0)
            {
                float num2 = block->ProjectileSpeed;
                num2 *= 0.5f * (componentMiner->componentPlayer->componentLevel->getStrengthFactor() - 1.0f) + 1.0f;
                Projectile *projectile = m_projectiles->fireProjectile(slotValue, vector, v * num2, GameSingleton::gameRandom->getVector3(5.0f, 10.0f), componentMiner->componentCreature);
                if (projectile != nullptr)
                {
                    uint32_t count = componentMiner->inventory->removeSlotItems(activeSlotIndex, 1);
                    if (count == 0)
                    {
                        projectile->toRemove = true;
                    }
                }
            }
            return true;
        }
        return false;
    }

    static const std::string subsystemName = "ThrowableBlockBehavior";
    const std::string &SubsystemThrowableBlockBehavior::getName() const
    {
        return subsystemName;
    }
    void SubsystemThrowableBlockBehavior::load(const nlohmann::json &json)
    {
        m_projectiles = GameSingleton::singletonPtr->getSingleton<SubsystemProjectiles>();
    }
}